﻿using MiniFox.Infrastructure.Attributes;
using MiniFox.Utility;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace MiniFox.Infrastructure
{
    /// <summary>
    /// 树组
    /// </summary>
    /// <typeparam name="D">自联结构元数据对象</typeparam>
    public class TreeGroup<D> : TreeGroupBase<D>
    {
        IEnumerable<D> _flatData;
        PropertyInfo _uniqueProperty;
        PropertyInfo _superProperty;
        PropertyInfo _sortProperty;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="groupId"></param>
        /// <param name="groupFlatData"></param>
        public TreeGroup(object groupId, IEnumerable<D> groupFlatData) : base(groupId)
        {
            _flatData = groupFlatData;
            var type = typeof(D);
            var attr = type.GetCustomAttribute<TreeNodeAttribute>();
            this.NodeKey = attr.NodeKey;
            this.SuperKey = attr.SuperKey;
            this.SortKey = attr.SortKey;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="groupId"></param>
        /// <param name="nodeKey"></param>
        /// <param name="superKey"></param>
        /// <param name="sortKey"></param>
        /// <param name="groupFlatData"></param>
        public TreeGroup(object groupId, string nodeKey, string superKey, string sortKey, IEnumerable<D> groupFlatData) : base(groupId)
        {
            _flatData = groupFlatData;

            this.NodeKey = nodeKey;
            this.SuperKey = superKey;
            this.SortKey = sortKey;

        }
        /// <summary>
        /// 分组内扁平化原始数据(自关联数据)
        /// </summary>
        public IEnumerable<D> FlatData
        {
            get
            {
                return _flatData;
            }
        }
        #region internal
        /// <summary>
        /// 
        /// </summary>
        private PropertyInfo UniqueProperty
        {
            get
            {
                if (_uniqueProperty == null)
                    _uniqueProperty = typeof(D).GetProperty(this.NodeKey);
                return _uniqueProperty;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        private PropertyInfo SuperProperty
        {
            get
            {
                if (_superProperty == null)
                    _superProperty = typeof(D).GetProperty(this.SuperKey);
                return _superProperty;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        private PropertyInfo SortProperty
        {
            get
            {
                if (_sortProperty == null)
                    _sortProperty = typeof(D).GetProperty(this.SortKey);
                return _sortProperty;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="flatDataItem"></param>
        /// <returns></returns>
        protected override object GetUniqueID(D flatDataItem)
        {
            return this.UniqueProperty.GetValue(flatDataItem);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="flatDataItem"></param>
        /// <returns></returns>
        protected override object GetSuperID(D flatDataItem)
        {
            return this.SuperProperty.GetValue(flatDataItem);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="flatDataItem"></param>
        /// <returns></returns>
        protected override object GetSortValue(D flatDataItem)
        {
            return this.SortProperty.GetValue(flatDataItem);
        }
        #endregion

        /// <summary>
        /// 默认根数据
        /// </summary>
        protected override D RootData
        {
            get
            {
                D rootData = this.FlatData.SingleOrDefault(d =>
                {
                    var superId = this.GetSuperID(d);
                    return object.Equals(superId, this.GroupID); //根节点提取规则为父ID等于组ID
                });
                return rootData;
            }
        }
        private Func<D, bool> CreateWhereFunc(D superDataItem)
        {
            var sid = this.GetUniqueID(superDataItem);//父对象的ID
            return (childDataItem) =>
            {
                //取子对象的父ID
                var superId = this.GetSuperID(childDataItem);
                //取子对象的ID
                var id = this.GetUniqueID(childDataItem);
                //返回子对象的父ID等于父对象的ID 并且 子对象的ID不等于父对象的ID
                return object.Equals(superId, sid) && !object.Equals(id, sid);
            };
        }
        /// <summary>
        /// 查找指定数据项的子集
        /// </summary>
        /// <param name="superDataItem"></param>
        /// <returns></returns>
        protected override IEnumerable<D> GetChildren(D superDataItem)
        {
            var children = this.FlatData.Where(this.CreateWhereFunc(superDataItem));
            return children;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="nodeId"></param>
        /// <returns></returns>
        public override ITreeNode CreateTreeByNodeID(object nodeId)
        {
            D nodeData = this.FlatData.SingleOrDefault(d =>
            {
                var id = this.GetUniqueID(d);
                return object.Equals(id, nodeId);
            });

            return CreateTree(nodeData, 0);
        }

    }

    /// <summary>
    /// 树组
    /// </summary>
    public class TreeGroup : TreeGroup<IDictionary<string, object>>
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="groupId"></param>
        /// <param name="nodeKey"></param>
        /// <param name="superKey"></param>
        /// <param name="sortKey"></param>
        /// <param name="groupFlatData"></param>
        public TreeGroup(object groupId, string nodeKey, string superKey, string sortKey, IEnumerable<IDictionary<string, object>> groupFlatData) : base(groupId, nodeKey, superKey, sortKey, groupFlatData)
        {
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="flatDataItem"></param>
        /// <returns></returns>
        protected override object GetUniqueID(IDictionary<string, object> flatDataItem)
        {
            return flatDataItem[this.NodeKey];
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="flatDataItem"></param>
        /// <returns></returns>
        protected override object GetSuperID(IDictionary<string, object> flatDataItem)
        {
            return flatDataItem[this.SuperKey];
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="flatDataItem"></param>
        /// <returns></returns>
        protected override object GetSortValue(IDictionary<string, object> flatDataItem)
        {
            return flatDataItem[this.SortKey];
        }
    }
}
